package com.liveneo.adapter.base.filter;

import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.util.List;
import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.apache.commons.lang3.StringUtils;
import org.springframework.web.context.WebApplicationContext;
import org.springframework.web.context.support.WebApplicationContextUtils;
import com.google.gson.JsonSyntaxException;
import com.liveneo.adapter.base.service.ConfigurationService;
import com.liveneo.adapter.base.support.AdapterConstants;
import com.liveneo.adapter.base.support.LogUtils;
import com.liveneo.adapter.base.support.ThreadStore;
import com.liveneo.adapter.mobile.model.BaseRequest;
import com.liveneo.adapter.mobile.model.BaseResponse;
import com.liveneo.adapter.mobile.service.MobileService;
import com.liveneo.adapter.mobile.support.MobileReturnCodeSupport;
import com.liveneo.system.base.utils.EncryptUtil;
import com.liveneo.system.base.utils.JsonUtils;
import com.liveneo.system.base.utils.RequestUtil;

/**
 * 移动端Http请求的过滤器
 * 
 * @author fucy
 *
 */
public class MobileHttpFilter implements Filter {
    @SuppressWarnings("unused")
    private MobileService        mobileService;
    private ConfigurationService configurationService;
    private List<String>         ignoreUrlList;

    /**
     * 初始化过滤器参数
     */
    @Override
    public void init(FilterConfig filterConfig) throws ServletException {
        WebApplicationContext applicationContext = WebApplicationContextUtils.getWebApplicationContext(filterConfig.getServletContext());
        // 从Spring上下文对象中获取Service类实例
        // mobileService = applicationContext.getBean(MobileService.class);
        configurationService = applicationContext.getBean(ConfigurationService.class);
        ignoreUrlList = configurationService.getIgnoreMobileUrlList();
    }

    /**
     * 过滤器处理
     */
    @SuppressWarnings("unused")
    @Override
    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
        try {
            ThreadStore.setCurRequestType(AdapterConstants.MODULE_TYPE_MOBILE);
            LogUtils.info("请求开始...");
            // 过滤器只能处理HTTP请求，否则抛出Servlet异常
            if (!(request instanceof HttpServletRequest) || !(response instanceof HttpServletResponse)) {
                this.responseErrorMsg(MobileReturnCodeSupport.CODE_NO_HTTP, null, response);
                return;
            }
            // 过滤器拦截的是http请求
            HttpServletRequest httpRequest = (HttpServletRequest) request;
            HttpServletResponse httpResponse = (HttpServletResponse) response;
            // 打印请求的url
            StringBuffer url = httpRequest.getRequestURL();
            LogUtils.info("请求的URL是：【" + url + "】");
            // 如果过滤器忽略此URL，直接返回
            if (isIgnoreMobileUrl(httpRequest.getServletPath())) {
                chain.doFilter(httpRequest, httpResponse);
                return;
            }
            // 获取参数值
            String jsonOriginalData = httpRequest.getParameter(AdapterConstants.MOBILE_REQUEST_PARAM_NAME);
            BaseResponse baseResponse = null;
            if (StringUtils.isBlank(jsonOriginalData)) {
                // 当无参数[data]时，记录一下当前传入的参数，以便出现此问题时的问题解决
                LogUtils.error("所有参数为【" + RequestUtil.convertParamtersToStr(httpRequest) + "】");
                // 无参数时，返回错误信息
                baseResponse = MobileReturnCodeSupport.buildBaseReponse(MobileReturnCodeSupport.CODE_ERR_PARAM,MobileReturnCodeSupport.SYS_CODE,
                        MobileReturnCodeSupport.CODE_ERR_PARAM_NO_EXISTS);
            } else {
                try {
                    // 记录原始参数日志【base64加密后】
                    LogUtils.info("原始参数值为【" + jsonOriginalData + "】");
                    // 将参数做Base64解密
                    String jsonData = EncryptUtil.decodeBase64String(jsonOriginalData);
                    // 记录解密后参数日志
                    LogUtils.info("解密后参数值为【" + jsonData + "】");
                    // json字符串转换为对象
                    BaseRequest baseRequest = (BaseRequest) JsonUtils.jsonToBean(jsonData, BaseRequest.class.getName());
                    // 版本判断是否为最新
                    // 认证是否通过
                    // 记录移动端请求日志
                } catch (Exception e) {
                    if (e instanceof UnsupportedEncodingException) {
                        // 参数base64解密时异常错误
                        baseResponse = MobileReturnCodeSupport.buildBaseReponse(MobileReturnCodeSupport.CODE_ERR_PARAM,MobileReturnCodeSupport.SYS_CODE,
                                MobileReturnCodeSupport.CODE_ERR_PARAM_FAILED_DECRYPT);
                    } else if (e instanceof JsonSyntaxException) {
                        // 参数json转换成对象时异常错误
                        baseResponse = MobileReturnCodeSupport.buildBaseReponse(MobileReturnCodeSupport.CODE_ERR_PARAM,MobileReturnCodeSupport.SYS_CODE,
                                MobileReturnCodeSupport.CODE_ERR_PARAM_FAILED_TO_OBJ);
                    } else {
                        // 其他内部错误
                        baseResponse = MobileReturnCodeSupport.buildBaseReponse(MobileReturnCodeSupport.CODE_INTERNAL_ERROR,MobileReturnCodeSupport.SYS_CODE, null);
                    }
                    LogUtils.error(baseResponse.getExtMessage(), e);
                }
            }
            // 存在响应信息，过滤器的认证不通过，返回错误信息
            if (baseResponse != null) {
                // 记录日志
                responseErrorMsg(baseResponse, httpResponse);
                return;
            }
            chain.doFilter(httpRequest, httpResponse);
        } finally {
            LogUtils.info("请求结束...");
            // 手动清空当前线程的内容
            ThreadStore.clear();
        }
    }

    /**
     * 根据错误码返回相应信息
     * 
     * @param code 错误码
     * @param detailCode 详细错误码
     * @param response 
     * @throws IOException 
     */
    private void responseErrorMsg(String code, String detailCode, ServletResponse response) throws IOException {
        // 构建响应对象
        BaseResponse baseResponse = MobileReturnCodeSupport.buildBaseReponse(code,MobileReturnCodeSupport.SYS_CODE, detailCode);
        responseErrorMsg(baseResponse, response);
    }

    /**
     * 根据响应对象返回信息
     * 
     * @param baseResponse 响应对象
     * @param response
     * @throws IOException 
     */
    private void responseErrorMsg(BaseResponse baseResponse, ServletResponse response) throws IOException {
        // 将响应对象转换成Json字符串
        String jsonStr = JsonUtils.beanToJson(baseResponse);
        LogUtils.error("响应json字符串【" + jsonStr + "】");
        // base64编码
        String jsonStrWithBase64 = EncryptUtil.encodeBase64(jsonStr);
        LogUtils.error("响应编码后字符串【" + jsonStrWithBase64 + "】");
        // 设置响应编码
        response.setCharacterEncoding("UTF-8");
        // 返回响应内容
        response.getWriter().write(jsonStrWithBase64);
    }

    /**
     * 判断是否为过滤器忽略的URL
     * 
     * @return
     */
    private boolean isIgnoreMobileUrl(String url) {
        return ignoreUrlList != null ? ignoreUrlList.contains(url) : false;
    }

    /**
     * 销毁过滤器前，销毁对象
     */
    @Override
    public void destroy() {
        mobileService = null;
        configurationService = null;
        ignoreUrlList = null;
    }
}
